package com.atguigu.gmallpublisher.esdao;


import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmallpublisher.beans.Option;
import com.atguigu.gmallpublisher.beans.SaleDetail;
import com.atguigu.gmallpublisher.beans.Stat;
import io.searchbox.client.JestClient;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import io.searchbox.core.search.aggregation.MetricAggregation;
import io.searchbox.core.search.aggregation.TermsAggregation;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.TermsBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;


@Repository
public class ESDaoImp implements ESDao{
    @Autowired
    private JestClient jest;

    @Override
    public JSONObject getOrderDetail(String date, Integer startpage, Integer size, String keyword) throws IOException {
        SearchResult result = getDataFromES(date, startpage, size, keyword);
        Long total = result.getTotal();
        List<SaleDetail> detail = getDetail(result);

        List<Option> genderCount = getGenderCount(result);

        List<Option> ageCount = getAgeCount(result);

        Stat ageStat = new Stat("用户年龄占比", ageCount);
        Stat genderStat = new Stat("用户性别占比", genderCount);

        ArrayList<Stat> stats = new ArrayList<>();
        stats.add(ageStat);
        stats.add(genderStat);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("stat", stats);
        jsonObject.put("detail",detail);
        jsonObject.put("total",total);
        System.out.println(jsonObject.toJSONString());
        return jsonObject;
    }

    public SearchResult getDataFromES(String date, Integer startpage, Integer size, String keyword) throws IOException {
        //从es查询数据
        /*GET gmall2020_sale_detail-query/_search
{
  "query": {
    "match": {
      "sku_name": "小米手机"
    }
  },
  "aggs": {
    "gender_count": {
      "terms": {
        "field": "user_gender",
        "size": 10
      }
    },
    "age_count": {
      "terms": {
        "field": "user_age",
        "size": 200
      }
    }
  }
}*/
        //实现上述查询命令
        int from = (startpage - 1) * 10;
        String indexName = "gmall2020_sale_detail" + date;
        MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("sku_name", keyword);
        TermsBuilder user_gender = AggregationBuilders.terms("gender_count").field("user_gender").size(10);
        TermsBuilder user_age = AggregationBuilders.terms("age_count").field("user_age").size(200);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder().
                query(matchQueryBuilder).
                aggregation(user_age).
                aggregation(user_gender).
                from(from).
                size(size);
        Search build = new Search.Builder(sourceBuilder.toString()).
                addIndex(indexName).addType("_doc").build();
        SearchResult result = jest.execute(build);

        return result;
    }
    //根据预先设置好的响应体结构封装detail,detail是个json数组,数组里面是一个个saledetail
    public List<SaleDetail> getDetail(SearchResult result){

        List<SaleDetail> list = new ArrayList<>();

        List<SearchResult.Hit<SaleDetail, Void>> hits = result.getHits(SaleDetail.class);
        for (SearchResult.Hit<SaleDetail, Void> hit : hits) {
            SaleDetail saleDetail = hit.source;
            saleDetail.setEs_metadata_id(hit.id);
            list.add(saleDetail);
        }
        return list;
    }
    //根据预先设置好的响应体结构封装男女比例option
    public List<Option> getGenderCount(SearchResult result){

        List<Option> list = new ArrayList<>();

        MetricAggregation aggregations = result.getAggregations();
        TermsAggregation gender_count = aggregations.getTermsAggregation("gender_count");

        List<TermsAggregation.Entry> buckets = gender_count.getBuckets();
        double sumCount = 0.0;
        long manCount = 0;
        long femaleCount = 0;

        for (TermsAggregation.Entry bucket : buckets) {
            String name = bucket.getKey();
            if("F".equals(name)){
                Long value = bucket.getCount();
                manCount=value;
            }else{
                Long value = bucket.getCount();
                femaleCount=value;
            }
        }
        sumCount = manCount + femaleCount;
        DecimalFormat decimalFormat = new DecimalFormat("###.00");
        double manValue = Double.parseDouble(decimalFormat.format(manCount/sumCount*100));
        list.add(new Option("男",manValue));
        list.add(new Option("女",100-manValue));
        return list;
    }

    //根据预先设置好的响应体结构封装年龄比例option
    public List<Option> getAgeCount(SearchResult result){

        List<Option> list = new ArrayList<>();

        MetricAggregation aggregations = result.getAggregations();
        TermsAggregation age_count = aggregations.getTermsAggregation("age_count");

        List<TermsAggregation.Entry> buckets = age_count.getBuckets();

        long lt20 = 0;
        long gt20lt30 = 0;
        long gt30 = 0;
        for (TermsAggregation.Entry bucket : buckets) {
            if (Integer.parseInt(bucket.getKey()) < 20) {
                Long lt20count = bucket.getCount();
                lt20 += lt20count;
            } else if (Integer.parseInt(bucket.getKey()) >= 30) {
                gt30 += bucket.getCount();
            } else {
                gt20lt30 += bucket.getCount();
            }
        }
        DecimalFormat decimalFormat = new DecimalFormat("###.00");
        double sum = lt20 + gt30 + gt20lt30;
        double lt20percent = Double.parseDouble(decimalFormat.format(lt20 / sum *100));
        double gt30percent = Double.parseDouble(decimalFormat.format(gt30 / sum *100));
        double gt20lt30percent = 100 - lt20percent - gt30percent;
        list.add(new Option("20岁以下",lt20percent));
        list.add(new Option("20岁到30岁",gt20lt30percent));
        list.add(new Option("30岁以上",gt30percent));
        return list;
    }
}
